在Swift 2中,即使函数中没有任何调用可以抛出,下面的函数也不会编译.
func function1(f: Optional U>, x: Optional ) -> Optional { return f.flatMap(x.map) // Call can throw, but it is not marked with 'try' and the error is not handled }
此版本的函数与第一个版本相同(并且更详细),但它编译.
func function2(f: Optional U>, x: Optional ) -> Optional { return f.flatMap { g in x.map(g) } }
mixel.. 6
这些版本不完全相同,我解释原因.
假设你有函数,rethrows
因为它接受抛出函数作为参数:
func a(x: () throws -> ()) rethrows { try x() }
所以a(x)
只有投掷才会x()
抛出.
如果你有b
抛出的功能:
func b() throws { }
然后你必须a(b)
用try 调用:
try a(b) a(b) // gives "Call can throw but is not marked with 'try'"
但如果你传递给a
不投掷功能:
func c() { }
然后斯威夫特编译器足够聪明,以确定x()
在a
函数体实际上不扔,它允许简单地调用a(c)
:
a(c) // it's ok
这是因为:
throws关键字是函数类型的一部分,nonthrowing函数是抛出函数的子类型.因此,您可以在与抛出函数相同的位置使用非抛出函数.
回到你的例子.
Optional.flatMap()
定义为:
public func flatMap(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
在你的例子中f.flatMap
有类型((T -> U) throws -> U?) rethrows -> U?
.
你看到它重新抛出,因为它接受抛出函数参数并且必须被调用,try
除非f
有类型Wrapped -> U?
并且不抛出.
Optional.map
定义为:
public func map(@noescape f: (Wrapped) throws -> U) rethrows -> U?
所以x.map
有型(T throws -> U) rethrows -> U?
.
当你调用f.flatMap { g in x.map(g) }
编译器看到它g
有T -> U
类型并且不抛出时x.map(g)
,{ g in x.map(g) }
并且f.flatMap { g in x.map(g) }
都是安全的并且不抛出.
但是,当你调用f.flatMap(x.map)
所有编译器看到的那个x.map
有 (T throws -> U) rethrows -> U?
类型并且可以(重新)抛出因此f.flatMap(x.map)
不安全而且可以(重新)抛出并且必须被调用时try
.
这些版本不完全相同,我解释原因.
假设你有函数,rethrows
因为它接受抛出函数作为参数:
func a(x: () throws -> ()) rethrows { try x() }
所以a(x)
只有投掷才会x()
抛出.
如果你有b
抛出的功能:
func b() throws { }
然后你必须a(b)
用try 调用:
try a(b) a(b) // gives "Call can throw but is not marked with 'try'"
但如果你传递给a
不投掷功能:
func c() { }
然后斯威夫特编译器足够聪明,以确定x()
在a
函数体实际上不扔,它允许简单地调用a(c)
:
a(c) // it's ok
这是因为:
throws关键字是函数类型的一部分,nonthrowing函数是抛出函数的子类型.因此,您可以在与抛出函数相同的位置使用非抛出函数.
回到你的例子.
Optional.flatMap()
定义为:
public func flatMap(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
在你的例子中f.flatMap
有类型((T -> U) throws -> U?) rethrows -> U?
.
你看到它重新抛出,因为它接受抛出函数参数并且必须被调用,try
除非f
有类型Wrapped -> U?
并且不抛出.
Optional.map
定义为:
public func map(@noescape f: (Wrapped) throws -> U) rethrows -> U?
所以x.map
有型(T throws -> U) rethrows -> U?
.
当你调用f.flatMap { g in x.map(g) }
编译器看到它g
有T -> U
类型并且不抛出时x.map(g)
,{ g in x.map(g) }
并且f.flatMap { g in x.map(g) }
都是安全的并且不抛出.
但是,当你调用f.flatMap(x.map)
所有编译器看到的那个x.map
有 (T throws -> U) rethrows -> U?
类型并且可以(重新)抛出因此f.flatMap(x.map)
不安全而且可以(重新)抛出并且必须被调用时try
.